﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CobaCoba.AccountInquiry;
using System.IO;
using System.Data.Odbc;
using System.Data;
using System.Threading.Tasks;
using Newtonsoft.Json;
using AmazedSaint.Elastic.Lib;
using AmazedSaint.Elastic;
using System.Xml.Linq;
using System.Collections.Concurrent;
using Magnum.Reflection;
using System.Reflection;
using System.Collections;
using SwiftNet.Impl.Mt;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SwiftNet.Models;
using SwiftNet.Impl.Fields;
//using Renci.SshNet.Sftp;
//using Renci.SshNet;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.Threading;

namespace CobaCoba
{
    class Program
    {
        private static Dictionary<Type, Dictionary<string, FastProperty>> typeCache =
            new Dictionary<Type, Dictionary<string, FastProperty>>();



        private static void SetupObjectPropertiesChache(Type msgType)
        {
            ElementInAttribute[] el;

            lock (msgType)
            {
                if (!typeCache.ContainsKey(msgType))
                {
                    var propCacheTmp = new Dictionary<string, FastProperty>();
                    typeCache.Add(msgType, propCacheTmp);

                    foreach (PropertyInfo pi in msgType.GetProperties())
                    {
                        el = (ElementInAttribute[])pi.GetCustomAttributes(typeof(ElementInAttribute), true);
                        if (el != null && el.Length == 1)
                        {
                            propCacheTmp.Add(el[0].Element, new FastProperty(pi));
                        }
                    }
                }
            }
        }
        private static TimerThread tt;// = new TimerThread();

        private enum testenum
        {
            deky =0,
            yanuar=1
        }
        delegate bool bol(int x);
        static bol bl;
        
        static void Main(string[] args)
        {
            iasync();
         //   lambda();
            Console.WriteLine("Done");
            Console.ReadKey();
            return;
            localhost.Service svc = new localhost.Service();
            var o = svc.getlistemp();

            return;

            #region sftp


            //using (var sf = new SftpClient("192.168.1.115", "praweda", "password"))
            //{
            //    try
            //    {
            //        //string s = Path.GetFileName("c:\\btrv.log");
            //        Console.WriteLine("trying...");
            //        sf.Connect();


            //        using (var file = File.OpenRead("c:\\HOLDING.CSV"))
            //        {
            //            sf.UploadFile(file, "d:\\ade" + DateTime.Now.ToString("HHmmss"));
            //        }
            //        Console.WriteLine("done");
            //        sf.Disconnect();
            //    }
            //    catch (Exception ex)
            //    {

            //        Console.WriteLine(ex.Message);
            //    }
            //}
            //Console.ReadKey();

            //return; 
            #endregion

            TestCreateMT190();
            TestMT190();
            Console.ReadKey();

            return;
            #region old

            var f = Type.GetType("CobaCoba.InstructionData");
            var otask = Activator.CreateInstance(f);

            //            SetupObjectPropertiesChache(typeof(AckInstruction));
            SetupObjectPropertiesChache(f);
            var propCache = typeCache[f];
            //InstructionData otask= new InstructionData();
            //AckInstruction otask = new AckInstruction();

            //instruksi
            string sv = "<Messages name=\"InstructionData\" MessageID=\" INCOMING999999999999999999999999999999\" type =\"IncomingMessage\" action=\"UPDATE\"><Record name=\"recordInstruction\"><Field name=\"accountParticipantCash\"></Field><Field name=\"reimbursementDate\">20061108</Field><Field name=\"instructionType\">DVP</Field><Field name=\"relatedInstruction\">0cbf100000010ec50c998a82c90133</Field><Field name=\"counterParty\">LG001</Field><Field name=\"canceling\">FALSE</Field><Field name=\"currency\">IDR</Field><Field name=\"accountParticipant\">OD001000000171</Field><Field name=\"blockingReason\"></Field><Field name=\"status\">CANCELLED</Field><Field name=\"settlementDate\">20061108</Field><Field name=\"securityQuantity\">100</Field><Field name=\"matchable\">TRUE</Field><Field name=\"accountCounterParty\"></Field><Field name=\"externalReference\">DVP_KSEILOGIN_EQUITY_SMCB_K03</Field><Field name=\"settlementAmount\">100000</Field><Field name=\"externalBankAccount\"></Field><Field name=\"description\">DESCR</Field><Field name=\"lastUpdateTimestamp\">20061109060247842</Field><Field name=\"security\">ADES</Field><Field name=\"tradeDate\">20061108</Field><Field name=\"uniqueIdentifier\">0cbf0c0000010ec50c998a82c90133</Field><Field name=\"priority\">M</Field>C-BEST InterfaceHalaman 37<Field name=\"participant\">OD001</Field></Record></Messages>";
            //ack ok
            //string sv="<Messages name=\"AckInstruction\" type=\"IncomingMessage\" MessageID=\"INCOMING4466042c32e7058797137b963b030da0\"><Record name=\"data\"><field name=\"externalReference\">A-DX-20130927-0000-XR67-IDR-COLDS</field><field name=\"participantCode\">DX001</field><field name=\"sourceAccount\">DX001000000116</field><field name=\"targetAccount\">DX001XR6700110</field><field name=\"currencyCode\">IDR</field><field name=\"securityCodeType\" /><field name=\"securityCode\" /><field name=\"instrumentQuantity\">5475000.00</field><field name=\"settlementDate\">20130927</field><field name=\"description\" /></Record></Messages>"

            //ack not ok
            //string sv="<Messages name=\"AckInstruction\" MessageID=\"INCOMING0ec522d7cd1362aa44c2ce0a9e0579b9\" type=\"IncomingMessage\"><Record name=\"data\"><field name=\"externalReference\">A-DX-20130927-0000-XR67-IDR-COLDS</field><field name=\"participantCode\">DX001</field><field name=\"sourceAccount\">DX001000000116</field><field name=\"targetAccount\">DX001XR6700110</field><field name=\"currencyCode\">IDR</field><field name=\"securityCodeType\" /><field name=\"securityCode\" /><field name=\"instrumentQuantity\">5475000.00</field><field name=\"settlementDate\">20130927</field><field name=\"description\" /></Record><!-- Error(s) for this record --><Record name=\"error\"><ListError><!-- OnField - EXT_REF --><Field name=\"errorCode\">901</Field><Field name=\"errorMessage\">Error: 901 - Duplicate message 'A-DX-20130927-0000-XR67-IDR-COLDS'</Field></ListError></Record></Messages>";

            ElasticObject message = XElement.Parse(sv).ToElastic();


            var typeMsg = (string)message.GetAttributeValue("name");

            CBestIncomingMessage cig = new CBestIncomingMessage();
            int cnt = 0;
            IEnumerable<ElasticObject> le = message.Elements;
            foreach (var s in le)
            {
                if (s.InternalName == "Record")
                {
                    if (cnt == 0)
                    {
                        foreach (var fields in s.Elements)
                        {
                            var propName = fields.Attribute("name");
                            string propKey = (string)propName.InternalValue;

                            if (propCache.ContainsKey(propKey))
                            {
                                var fastPropreties = propCache[propKey];
                                string propVal = fields.InternalValue == null ? string.Empty : (string)fields.InternalValue;
                                fastPropreties.Set(otask, propVal);
                            }
                        }
                    }
                    else
                    {
                        var strChildType = s.GetAttributeValue("name") == null ? string.Empty : (string)s.GetAttributeValue("name");
                        if (strChildType.ToLower() == "error")
                        {
                            cig.ErrMsg = s.InternalValue == null ? string.Empty : (string)s.InternalValue;
                        }
                    }
                    cnt++;
                }
            }



            cig.Fill((ImessageContent)otask);
            cig.CTAgentMessageId = string.Format("row.MessageId - {0}", DateTime.Now);
            cig.IncomingId = Guid.NewGuid();
            if (!string.IsNullOrEmpty(cig.ErrMsg))
            {
                cig.MsgContent.Status = "rej";

            }
            else
            {
                if (string.IsNullOrEmpty(cig.MsgContent.Status))
                {
                    cig.MsgContent.Status = "accept";// MessageStatus._StatusAcceptedCT;
                }
            }

            ArrayList ar = new ArrayList();
            ar.Add(cig);



            //CBestOutgoingMessage cog = new OTC();
            //var k= JsonConvert.DeserializeObject<InstructionData>(sv);
            //CastDerivedToBase cb = new CastDerivedToBase();
            //cb.Casting<InstructionData,ImessageContent>(

            //Console.WriteLine("test"); 
            #endregion
            Console.ReadKey();

        }
        static void iasync()
        {
            //var t = new bol(procc);

            //t.BeginInvoke(2,null,null);
            Func<int, string> f = x => "kk";
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.

            IAsyncResult r = f.BeginInvoke(3, null, null);

            //IAsyncResult result = caller.BeginInvoke(3000,
            //    out threadId, null, null);

            //Thread.Sleep(0);
            //Console.WriteLine("Main thread {0} does some work.",
            //    Thread.CurrentThread.ManagedThreadId);

            //// Wait for the WaitHandle to become signaled.
            //result.AsyncWaitHandle.WaitOne();


            //// Perform additional processing here. 
            //// Call EndInvoke to retrieve the results. 
            //string returnValue = caller.EndInvoke(out threadId, result);

            //// Close the wait handle.
            //result.AsyncWaitHandle.Close();

            //Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
            //    threadId, returnValue);

            Console.WriteLine("kokokokokokokok");
        }
    
        // The delegate must have the same signature as the method 
        // it will call asynchronously. 
        public delegate string AsyncMethodCaller(int callDuration, out int threadId);


        static void lambda()
        {

            int?[] data = new int?[] { 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 2, 4, 6, 9, 3, 4, 6, 9, null, 2, 3, 7, 4, 8, 9, 4, 7, 7, 0, 7, 3, 2, 5, 6, 7, null, 8, 0, 6, 4, 6, 8, 5, 0, 3, 8, 5, 7, 0, 3, 4, 8, 7, 3, 5, 9, 7, 6, 3, 5, 8, 7, 6, 3, 5, 8, 7, 0, 9, 3, 2, 8, 4, 5, 7, 2, 8, 4, 7, 5, 6 };
            List<emp> cdata = new List<emp>();
            int[] dj = new int[] { 1, 1, 3, 5, 7, 9, 9 };
            int[] dg = new int[] { 2, 4, 6, 4, 8, 0 };
            List<int> lint = new List<int>() { 1, 2, 4, 5, 6, 7, 8 };

            string sentence = "the quick brown fox jumps over the lazy dog";
            string[] words = sentence.Split(' ');

            string balik = words.Aggregate((hasilnya, stringitem) => stringitem + " " + hasilnya);


            //var c = data.Count<int>();
            //var c = data.Max();

            //var c = data.Where(x => x == 0).OrderBy(x => x).Count();
            //var c = data.Any<int>(x => x == 2); //result true;
            //var c = data.Where(x => !(new int[] { 4, 8 }).Contains(x)).Distinct<int>().OrderBy(x=>x); //in not in clause
            //var c = data.Where(x => x != null).Distinct<int?>().OrderBy(x=>x);
            //var c = dj.Union<int>(dg);
            //var c = dj.Aggregate<int>(x=>sun

            //var c = dj.Aggregate((t, i) => t+ i);
            //var c = lint.Where(x => x > 6).Sum();
            //var c = data.Count(x => x % 2 == 1);            
            //var c = data.Where(n => n % 2 == 1); //ganjil
            
            //Func<string, string> f = x => x +" ini";
            //func(dj, k => k > 5);

            //Func<string, string> f = x => x + "sdf";
            //Func<int, int, int> f = (x, y) => x * y + 1 - 10 * 5;            
            //var c = f(3,4);

            //var c = data.TakeWhile((n,indx) => n >indx); //return item that greater than indexer
            //var c = data.TakeWhile(n => n < 9);
            //bl = (x) => { return x == 2; };
            Func<int, bool> f = x => x == 2;
            var c = f(3);




            Console.WriteLine(c);
        }
        static bool procc(int o)
        {
            return true;
        }
        static int proc(int x,int y)
        {
            return x+y;
        }
        static void func(int[] src,Func<int, bool> f)
        {
            var c = src.Where(f);
            
            
           // f = x => x + 3;

            Console.WriteLine();
        }

        
        static void tt_TimerFired(object sender, TimerFiredArgs args)
        {
            tt.Pause();
            
            Console.WriteLine("fired:"+DateTime.Now);
            Thread.Sleep(3000);
            tt.Resume();
        }



        public static void TestMT190()
        {
            var mt190Str = new StringBuilder()
                .AppendLine("{1:F01INDOIDJAXXXX0001000011}{2:O9901800120322INDOIDJRXXXX00010000991203221800N}{3:{113:0070}}{4:")
                .AppendLine(":20:R1812057/990")
                .AppendLine(":21:NONREF")
                .AppendLine(":25:523014000990")
                .AppendLine(":32C:120322IDR14000000,")
                .AppendLine(":52A:CENAIDJA")
                .AppendLine(":71B:NONE")
                .AppendLine(":72:/INT/")
                .AppendLine("-}").ToString();
            Console.WriteLine(mt190Str);
            var conv = new SwiftNet.IO.ConversionService();
            var msg = conv.GetMessageFromFIN(mt190Str);

            var mt190 = new MT190(msg);
            Assert.AreEqual("R1812057/990", mt190.Field<Field20>().Value);
            Assert.AreEqual("NONREF", mt190.Field<Field21>().Value);
            Assert.AreEqual("523014000990", mt190.Field<Field25>().Value);

            Assert.AreEqual("120322IDR14000000,", mt190.Field<Field32C>().Value);

            Assert.AreEqual("CENAIDJA", mt190.Field<Field52A>().Value);
            Assert.AreEqual("NONE", mt190.Field<Field71B>().Value);
            Assert.AreEqual("/INT/", mt190.Field<Field72>().Value);
            mt190.Field<Field71B>().Components[1] = "FILL";
            mt190.UpdateTags();
            Console.WriteLine(conv.GetFIN(msg));
            mt190.Field<Field71B>().Components[1] = "NONE";
            mt190.UpdateTags();
            Console.WriteLine(conv.GetFIN(msg));
        }

        public static void TestCreateMT190()
        {
            var mt190Str = new StringBuilder()
                .AppendLine("{1:F01INDOIDJAXXXX0001000011}{2:O1901800120322INDOIDJRXXXX00010000991203221800N}{3:{113:0070}}{4:")
                .AppendLine(":20:R1812057/990")
                .AppendLine(":21:NONREF")
                .AppendLine(":25:523014000990")
                .AppendLine(":32C:120322IDR14000000,")
                .AppendLine(":52A:CENAIDJA")
                .AppendLine(":71B:NONE")                
                .AppendLine(":72:/INT/")
                .Append("-}").ToString();

            SwiftMessage m = new SwiftMessage(false);
            m.Block1 = new SwiftBlock1("F", "01", "INDOIDJAXXXX", "0001", "000011");
            m.Block2 = new SwiftBlock2Output("190", "1800", "120322", "INDOIDJRXXXX", "0001", "000099", "120322", "1800", "N");
            m.Block3 = new SwiftBlock3(new Tag[] { new Tag("113", "0070") });
            m.Block4 = new SwiftBlock4();

            var mt190 = new MT190(m);
            mt190.FieldLists["20"].Add(new Field20("R1812057/990"));
            mt190.FieldLists["21"].Add(new Field21("NONREF"));
            mt190.FieldLists["25"].Add(new Field25("523014000990"));
            mt190.FieldLists["32C"].Add(new Field32C("120322IDR14000000,"));
            mt190.FieldLists["52A"].Add(new Field52A("CENAIDJA"));
            mt190.FieldLists["71B"].Add(new Field71B("NONE"));
            mt190.FieldLists["72"].Add(new Field72("/INT/"));

            mt190.UpdateTags();
            var conv = new SwiftNet.IO.ConversionService();
            Console.WriteLine(conv.GetFIN(m));
            Assert.AreEqual(mt190Str, conv.GetFIN(m));
        }
        //private CreateMessageFactoryObject(string typeObject)
        //{
        //    string strType = string.Format("Praweda.Messaging.CBEST.Message.Incoming.{0}, Praweda.Messaging.CBEST.Message",
        //           typeObject);

        //    return instanceCache.AddOrUpdate(strType, TypeMessageFactory.CreateTypeMessageFactory(strType), (x, y) => y);
        //}
    }

    public class AsyncDemo
    {
        // The method to be executed asynchronously. 
        public string TestMethod(int callDuration, out int threadId)
        {
            Console.WriteLine("Test method begins.");
            Thread.Sleep(callDuration);
            threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("after sleep");
            return String.Format("My call time was {0}.", callDuration.ToString());
        }
    }

    public class emp
    {
        public int i { get; set; }
        public string s { get; set; }
            private  void jdsf()
            {
            }
    }
    public class Impersonation : IDisposable
    {
        private readonly SafeTokenHandle _handle;
        private readonly WindowsImpersonationContext _context;

        const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

        public Impersonation(string domain, string username, string password)
        {
            if (string.IsNullOrEmpty(username))
                return;
            var ok = LogonUser(username, domain, password,
                           LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
            if (!ok)
            {
                var errorCode = Marshal.GetLastWin32Error();
                throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
            }

            this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
        }

        public void Dispose()
        {
            if (this._context != null)
            {
                this._context.Undo();
                this._context.Dispose();
            }
            if (this._handle != null)
            {
                this._handle.Close();
                this._handle.Dispose();
            }
        }

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            private SafeTokenHandle()
                : base(true) { }

            [DllImport("kernel32.dll")]
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [SuppressUnmanagedCodeSecurity]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr handle);

            protected override bool ReleaseHandle()
            {
                return CloseHandle(handle);
            }
        }
    }

    public static class ext
    {
        public static Motor anu(this sepeda s)
        {
            return new Motor();
        }

        public static string ganti(this string s)
        {
            return "ganti";
        }
    }


    public class Motor
    {
        public string merk { get; set; }
    }

    public class sepeda
    {
        public string merk { get; set; }
    }

}

